﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace NetWork.Enthernet
{
    /// <summary>
    /// 文件传输客户端基类，提供上传，下载，删除的基础服务
    /// </summary>
    public abstract class FileClientBase : NetworkXBase
    {
        #region Private Member
        private IPEndPoint m_ipEndPoint = null;
        #endregion
        #region Public Member
        /// <summary>
        /// 服务器端的文件管理引擎终结点
        /// </summary>
        public IPEndPoint ServerIpEndPoint
        {
            get { return m_ipEndPoint; }
            set { m_ipEndPoint = value; }
        }
        private int connectTimeOut = 10000;
        /// <summary>
        /// 获取或设置连接的超时时间，默认10秒
        /// </summary>
        public int ConnectTimeOut
        {
            get { return connectTimeOut; }
            set { connectTimeOut = value; }
        }
        #endregion
        #region Private Method
        /// <summary>
        /// 发送三个文件分类到服务器端
        /// </summary>
        /// <param name="socket">套接字对象</param>
        /// <param name="factory">一级分类</param>
        /// <param name="group">二级分类</param>
        /// <param name="id">三级分类</param>
        /// <returns>是否成功的结果对象</returns>
        protected Result SendFactoryGroupId(
            Socket socket,
            string factory,
            string group,
            string id
            )
        {
            Result factoryResult = SendStringAndCheckReceive(socket, 1, factory);
            if (!factoryResult.Success)
            {
                return factoryResult;
            }
            Result groupResult = SendStringAndCheckReceive(socket, 2, group);
            if (!groupResult.Success)
            {
                return groupResult;
            }
            Result idResult = SendStringAndCheckReceive(socket, 3, id);
            if (!idResult.Success)
            {
                return idResult;
            }
            return Result.CreateSuccessResult(); ;
        }
        #endregion
        #region Delete File
        /// <summary>
        /// 删除服务器上的文件
        /// </summary>
        /// <param name="fileName">文件的名称</param>
        /// <param name="factory">一级分类</param>
        /// <param name="group">二级分类</param>
        /// <param name="id">三级分类</param>
        /// <returns>是否成功的结果对象</returns>
        protected Result DeleteFileBase(string fileName, string factory, string group, string id)
        {
            // connect server
            Result<Socket> socketResult = CreateSocketAndConnect(ServerIpEndPoint, ConnectTimeOut);
            if (!socketResult.Success) return socketResult;
            // 发送操作指令
            Result sendString = SendStringAndCheckReceive(socketResult.Data, HslProtocol.ProtocolFileDelete, fileName);
            if (!sendString.Success) return sendString;
            // 发送文件名以及三级分类信息
            Result sendFileInfo = SendFactoryGroupId(socketResult.Data, factory, group, id);
            if (!sendFileInfo.Success) return sendFileInfo;
            // 接收服务器操作结果
            Result<int, string> receiveBack = ReceiveStringContentFromSocket(socketResult.Data);
            if (!receiveBack.Success) return receiveBack;
            Result result = new Result();
            if (receiveBack.Data1 == 1) result.Success = true;
            result.Message = receiveBack.Message;
            socketResult.Data.Close();
            return result;
        }
        #endregion
        #region Download File
        /// <summary>
        /// 基础下载信息
        /// </summary>
        /// <param name="factory">一级分类</param>
        /// <param name="group">二级分类</param>
        /// <param name="id">三级分类</param>
        /// <param name="fileName">服务器的文件名称</param>
        /// <param name="processReport">下载的进度报告</param>
        /// <param name="source">数据源信息，决定最终存储到哪里去</param>
        /// <returns>是否成功的结果对象</returns>
        protected Result DownloadFileBase(
            string factory,
            string group,
            string id,
            string fileName,
            Action<long, long> processReport,
            object source
            )
        {
            // connect server
            Result<Socket> socketResult = CreateSocketAndConnect( ServerIpEndPoint, ConnectTimeOut );
            if (!socketResult.Success) return socketResult;
            // 发送操作指令
            Result sendString = SendStringAndCheckReceive( socketResult.Data, HslProtocol.ProtocolFileDownload, fileName );
            if (!sendString.Success) return sendString;
            // 发送三级分类
            Result sendClass = SendFactoryGroupId( socketResult.Data, factory, group, id );
            if (!sendClass.Success) return sendClass;
            string fileSaveName;
            Stream stream;
            // 根据数据源分析
            if (source is string)
            {
                fileSaveName=(string)source;
                Result result = ReceiveFileFromSocket( socketResult.Data, fileSaveName, processReport );
                if (!result.Success) return result;
            }
            else if (source is Stream)
            {
                stream=(Stream)source;
                Result result = ReceiveFileFromSocket( socketResult.Data, stream, processReport );
                if (!result.Success)
                {
                    return result;
                }
            }
            else
            {
                socketResult.Data.Close();
                Logger.LogWarn(ToString()+"输入的类型不支持，请重新输入" );
                return new Result("输入的类型不支持，请重新输入");
            }
            socketResult.Data.Close( );
            return Result.CreateSuccessResult( );
        }
        #endregion
        #region Upload File
        /// <summary>
        /// 上传文件给服务器
        /// </summary>
        /// <param name="source">数据源，可以是文件名，也可以是数据流</param>
        /// <param name="serverName">在服务器保存的文件名，不包含驱动器路径</param>
        /// <param name="factory">一级分类</param>
        /// <param name="group">二级分类</param>
        /// <param name="id">三级分类</param>
        /// <param name="fileTag">文件的描述</param>
        /// <param name="fileUpload">文件的上传人</param>
        /// <param name="processReport">汇报进度</param>
        /// <returns>是否成功的结果对象</returns>
        protected Result UploadFileBase(
            object source,
            string serverName,
            string factory,
            string group,
            string id,
            string fileTag,
            string fileUpload,
            Action<long, long> processReport)
        {
            // HslReadWriteLock readWriteLock = new HslReadWriteLock( );
            // 创建套接字并连接服务器
            Result<Socket> socketResult = CreateSocketAndConnect( ServerIpEndPoint, ConnectTimeOut );
            if (!socketResult.Success) return socketResult;
            // 上传操作暗号的文件名
            Result sendString = SendStringAndCheckReceive( socketResult.Data, HslProtocol.ProtocolFileUpload, serverName );
            if (!sendString.Success) return sendString;
            // 发送三级分类
            Result sendClass = SendFactoryGroupId( socketResult.Data, factory, group, id );
            if (!sendClass.Success) return sendClass;
            // 判断数据源格式
            if (source is string)
            {
               string  fileName=(string)source;
                Result result = SendFileAndCheckReceive( socketResult.Data, fileName, serverName, fileTag, fileUpload, processReport );
                if(!result.Success)
                {
                    return result;
                }
            }
            else if (source is Stream )
            {
                Stream stream = (Stream)source;
                Result result = SendFileAndCheckReceive( socketResult.Data, stream, serverName, fileTag, fileUpload, processReport );
                if (!result.Success)
                {
                    return result;
                }
            }
            else
            {
                socketResult.Data.Close( );
                Logger.LogWarn(ToString()+ "数据源格式不正确");
                return new Result("数据源格式不正确");
            }
            // 确认服务器文件保存状态
            Result<int, string> resultCheck = ReceiveStringContentFromSocket( socketResult.Data );
            if (!resultCheck.Success) return resultCheck;
            if (resultCheck.Data1 == 1)
            {
                return Result.CreateSuccessResult( );
            }
            else
            {
                return new Result("服务器确认文件失败，请重新上传");
            }
        }
        #endregion
        #region Object Override
        /// <summary>
        /// 获取本对象的字符串表示形式
        /// </summary>
        /// <returns>字符串信息</returns>
        public override string ToString()
        {
            return "FileClientBase";
        }
        #endregion
    }
}
